package com.sherlocky.resource.service;


import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import net.sf.ehcache.store.chm.ConcurrentHashMap;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.qiniu.util.Etag;
import com.rework.joss.persistence.convention.ConventionUtils;
import com.sherlocky.config.service.ConfigService;
import com.sherlocky.resource.common.ResourceContants;
import com.sherlocky.resource.dao.ResourceDAO;
import com.sherlocky.resource.dto.ResourceDTO;
import com.sherlocky.util.FileUtil;
import com.sherlocky.util.FileUtils;
import com.sherlocky.util.MD5Util;
import com.sherlocky.util.VFSUtil;

import conf.Constants;

@Service
@Transactional
public class ResourceService {
	private Log log = LogFactory.getLog(ResourceService.class);
	@Autowired
	private ResourceDAO resourceDAO;
	@Autowired
	private ConfigService configService;
	private static Map<String, Thread> map = new ConcurrentHashMap<String, Thread>();
	
	private static Map<String, List<Long>> counter = new ConcurrentHashMap<String, List<Long>>();
	private static Map<String, Thread> existTrans = new ConcurrentHashMap<String, Thread>();
	
	/**
	 * 前端调用七牛js上传完成后 保存文件
	 * @param hash
	 * @param key
	 * @param domain
	 * @param fileSize
	 * @return
	 */
	public ResourceDTO saveResource(String hash, String key, String domain, Long fileSize) {
		String suffix = FileUtils.getSuffix(key);
		ResourceDTO res = new ResourceDTO(hash, key, domain, fileSize, suffix, FileUtils.getFileType(suffix));
		resourceDAO.create(res);
		return res;
	}
	
	public void setMetainfo(ResourceDTO dto, String filepath) {
		dto.setTransFlag(ResourceDTO.TRANS_FLAG_ING);
	}
	
	public static void main(String[] args) throws IOException {
		System.out.println(Etag.file("D:\\Sherlocky\\Desktop\\44d2fff3.jpg"));
	}
	
	/**
	 * 计算上传过后文件的md5
	 * @param dto
	 */
	public void generateMD5(ResourceDTO dto){
		try {
			File file = new File(VFSUtil.getVFSPath(dto.getFilepath()));
			dto.setMd5(MD5Util.getFileMD5Checksum(file));
			resourceDAO.update(dto);
		}catch (Exception e) {
			log.error("生成md5失败"+ e.getMessage());
		}
	}
	/**
	 * 计算上传文件的md5，注意：计算完InputStream将会被关闭
	 * @param file
	 * @return
	 */
	public String generateMD5(InputStream InputStream) {
		String md5 = null;
		try {
			md5 =  MD5Util.getFileMD5Checksum(InputStream);
			return md5;
		}catch (Exception e) {
			log.error("生成md5失败"+ e.getMessage());
			return md5;
		}finally{
			IOUtils.closeQuietly(InputStream);
		}
	}
	/**
	 * 查找改学校存在的相同文件
	 * @param md5 文件md5值
	 * @param schoolId 学校id
	 * @return
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public ResourceDTO findResourceByMd5(String md5, String suffix) {
		if (StringUtils.isNotBlank(md5)) {
			List<ResourceDTO> list = resourceDAO.queryByCriteria("md5 = '" + md5 + "' AND suffix = '" + suffix +"'");
			if (list != null && list.size() > 0) {
				return list.get(0);
			}
		}
		return null;
	}
	
	/**
	 * 获取OSS服务器地址，以"/"结尾
	 * @return
	 */
	public String getOssServerUrl() {
		String url = configService.getValue("oss-server-url");
		if (StringUtils.isNotBlank(url) && !url.endsWith("/")) {
			url += "/";
		}
		return url;
	}
	
	/**
	 * 获取本地服务器视频播放地址
	 * @return
	 */
	public String getServerVideoPlayUrl() {
		return configService.getValue("fleaf-url-http") + "micro/play?id=";
	}
	
	public String getServerVideoPlayUrl(Long resourceId) {
		return getServerVideoPlayUrl(getServerVideoPlayUrl(), resourceId);
	}
	
	public String getServerVideoPlayUrl(String playUrl, Long resourceId) {
		String random = RandomStringUtils.randomAlphanumeric(5);
		String timestamp = System.currentTimeMillis() + "";
		return playUrl+ resourceId 
				+ "&random=" + random 
				+ "&timestamp=" + timestamp
				+ "&token=" + MD5Util.go2(random + resourceId + timestamp + Constants.ANONYMOUSE_ACCESS_PRIVATE_KEY).toUpperCase();
	}
	
	/**
	 * 处理超时还没有转码的文件，目前是1个小时
	 * @param dto 资源id及时间不能为空
	 */
	public void transferOverdueNotTransFile(ResourceDTO dto) {
		if(dto.getDateline() == null || dto.getId() == null) {
			return;
		}
		//查看上传时间如果超过了1小时，则调用转码接口
		if((System.currentTimeMillis() - dto.getDateline() * 1000) > DateUtils.MILLIS_PER_HOUR) {
			log.info("超过1个小时还不转码？直接转：" + dto.getId() + "," + dto.getFilepath());
			//TODO addResource2TransQueue(dto.getId());
		}
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public ResourceDTO getResourceById(Long id) {
		return resourceDAO.findById(id);
	}
	/**
	 * 获取转码文件路径
	 * @param resourceDTO 文件DTO
	 * @return  转码文件绝对路径
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public String getTransfilePath(ResourceDTO resourceDTO) {
		if( resourceDTO == null )return "";
		if(StringUtils.isBlank(resourceDTO.getTransfilePath())) return "";
		return VFSUtil.getVFSPath(resourceDTO.getTransfilePath());
	}
	/**
	 * 获取转码文件路径
	 * @param id 文件ID
	 * @return  转码文件绝对路径
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public String getTransfilePath(Long id) {
		return getTransfilePath(getResourceById(id));
	}
	/**
	 * 获取转码截图路径
	 * @param resourceDTO 文件DTO
	 * @return  转码截图绝对路径
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public String getTranspicPath(ResourceDTO resourceDTO) {
		if( resourceDTO == null )return "";
		if(StringUtils.isBlank(resourceDTO.getTranspicPath())) return "";
		return VFSUtil.getVFSPath(resourceDTO.getTranspicPath());
	}
	
	/**
	 * 获取转码截图路径
	 * @param id 文件ID
	 * @return  转码截图绝对路径
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public String getTranspicPath(Long id) {
		return getTranspicPath(getResourceById(id));
	}
	
	/**
	 * 获取资源文件路径
	 * @param id 文件ID
	 * @return 文件绝对路径
	 */
	@Transactional(propagation=Propagation.REQUIRED)
	public String getFilePath(Long id) {
		return getFilePath(getResourceById(id));
	}
	
	/**
	 * 获取资源文件路径
	 * @param resourceDTO 文件DTO
	 * @return  文件绝对路径
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public String getFilePath(ResourceDTO resourceDTO) {
		if( resourceDTO == null )return "";
		if(StringUtils.isBlank(resourceDTO.getFilepath())) return "";
		return VFSUtil.getVFSPath(resourceDTO.getFilepath());
	}
	
	public List<ResourceDTO> getResourceByIds(List<Long> resourceIds){
		return resourceDAO.queryByTpl("getResourceByIds", ConventionUtils.m("resourceIds",resourceIds));
	}
	public void updateResource(ResourceDTO resource){
		resourceDAO.update(resource);
	}
	/**
	 * 是否启用OSS存储方式
	 * @return
	 */
	public boolean isOssMode() {
		return configService.getBooleanValue("oss-mode");
	}
}
